#!/usr/bin/env python
# -*- encoding: utf-8 -*-

from mininet.net import Mininet
from mininet.topo import Topo
from mininet.node import Controller, RemoteController, OVSController
from mininet.node import CPULimitedHost, Host, Node
from mininet.node import OVSKernelSwitch, UserSwitch
from mininet.node import IVSSwitch
from mininet.cli import CLI
from mininet.log import setLogLevel, info
from mininet.link import TCLink, Intf
from subprocess import call


def _init(topo):
    info('*** Adding switches\n')
    s1 = topo.addSwitch('s1', cls=OVSKernelSwitch)
    s2 = topo.addSwitch('s2', cls=OVSKernelSwitch)
    s3 = topo.addSwitch('s3', cls=OVSKernelSwitch)
    s4 = topo.addSwitch('s4', cls=OVSKernelSwitch)
    s5 = topo.addSwitch('s5', cls=OVSKernelSwitch)
    s6 = topo.addSwitch('s6', cls=OVSKernelSwitch)
    s7 = topo.addSwitch('s7', cls=OVSKernelSwitch)
    s8 = topo.addSwitch('s8', cls=OVSKernelSwitch)
    s9 = topo.addSwitch('s9', cls=OVSKernelSwitch)
    s10 = topo.addSwitch('s10', cls=OVSKernelSwitch)
    s11 = topo.addSwitch('s11', cls=OVSKernelSwitch)
    s12 = topo.addSwitch('s12', cls=OVSKernelSwitch)
    s13 = topo.addSwitch('s13', cls=OVSKernelSwitch)
    s14 = topo.addSwitch('s14', cls=OVSKernelSwitch)
    s15 = topo.addSwitch('s15', cls=OVSKernelSwitch)
    s16 = topo.addSwitch('s16', cls=OVSKernelSwitch)
    s17 = topo.addSwitch('s17', cls=OVSKernelSwitch)
    s18 = topo.addSwitch('s18', cls=OVSKernelSwitch)
    s19 = topo.addSwitch('s19', cls=OVSKernelSwitch)
    s20 = topo.addSwitch('s20', cls=OVSKernelSwitch)
    s21 = topo.addSwitch('s21', cls=OVSKernelSwitch)
    s22 = topo.addSwitch('s22', cls=OVSKernelSwitch)
    s23 = topo.addSwitch('s23', cls=OVSKernelSwitch)
    s24 = topo.addSwitch('s24', cls=OVSKernelSwitch)
    s25 = topo.addSwitch('s25', cls=OVSKernelSwitch)
    s26 = topo.addSwitch('s26', cls=OVSKernelSwitch)
    s27 = topo.addSwitch('s27', cls=OVSKernelSwitch)
    s28 = topo.addSwitch('s28', cls=OVSKernelSwitch)
    s29 = topo.addSwitch('s29', cls=OVSKernelSwitch)
    s30 = topo.addSwitch('s30', cls=OVSKernelSwitch)
    s31 = topo.addSwitch('s31', cls=OVSKernelSwitch)
    s32 = topo.addSwitch('s32', cls=OVSKernelSwitch)
    s33 = topo.addSwitch('s33', cls=OVSKernelSwitch)
    s34 = topo.addSwitch('s34', cls=OVSKernelSwitch)
    s35 = topo.addSwitch('s35', cls=OVSKernelSwitch)
    s36 = topo.addSwitch('s36', cls=OVSKernelSwitch)
    s37 = topo.addSwitch('s37', cls=OVSKernelSwitch)
    s38 = topo.addSwitch('s38', cls=OVSKernelSwitch)
    s39 = topo.addSwitch('s39', cls=OVSKernelSwitch)
    s40 = topo.addSwitch('s40', cls=OVSKernelSwitch)
    s41 = topo.addSwitch('s41', cls=OVSKernelSwitch)
    s42 = topo.addSwitch('s42', cls=OVSKernelSwitch)
    s43 = topo.addSwitch('s43', cls=OVSKernelSwitch)
    s44 = topo.addSwitch('s44', cls=OVSKernelSwitch)
    s45 = topo.addSwitch('s45', cls=OVSKernelSwitch)
    s46 = topo.addSwitch('s46', cls=OVSKernelSwitch)
    s47 = topo.addSwitch('s47', cls=OVSKernelSwitch)
    s48 = topo.addSwitch('s48', cls=OVSKernelSwitch)
    s49 = topo.addSwitch('s49', cls=OVSKernelSwitch)
    s50 = topo.addSwitch('s50', cls=OVSKernelSwitch)
    s51 = topo.addSwitch('s51', cls=OVSKernelSwitch)
    s52 = topo.addSwitch('s52', cls=OVSKernelSwitch)
    s53 = topo.addSwitch('s53', cls=OVSKernelSwitch)
    s54 = topo.addSwitch('s54', cls=OVSKernelSwitch)
    s55 = topo.addSwitch('s55', cls=OVSKernelSwitch)
    s56 = topo.addSwitch('s56', cls=OVSKernelSwitch)
    s57 = topo.addSwitch('s57', cls=OVSKernelSwitch)
    s58 = topo.addSwitch('s58', cls=OVSKernelSwitch)
    s59 = topo.addSwitch('s59', cls=OVSKernelSwitch)
    s60 = topo.addSwitch('s60', cls=OVSKernelSwitch)
    s61 = topo.addSwitch('s61', cls=OVSKernelSwitch)
    s62 = topo.addSwitch('s62', cls=OVSKernelSwitch)
    s63 = topo.addSwitch('s63', cls=OVSKernelSwitch)
    s64 = topo.addSwitch('s64', cls=OVSKernelSwitch)
    s65 = topo.addSwitch('s65', cls=OVSKernelSwitch)
    s66 = topo.addSwitch('s66', cls=OVSKernelSwitch)

    info('*** Adding hosts\n')
    h1 = topo.addHost('h1', cls=Host, ip='10.0.0.1', defaultRoute=None)
    h2 = topo.addHost('h2', cls=Host, ip='10.0.0.2', defaultRoute=None)
    h3 = topo.addHost('h3', cls=Host, ip='10.0.0.3', defaultRoute=None)
    h4 = topo.addHost('h4', cls=Host, ip='10.0.0.4', defaultRoute=None)
    h5 = topo.addHost('h5', cls=Host, ip='10.0.0.5', defaultRoute=None)
    h6 = topo.addHost('h6', cls=Host, ip='10.0.0.6', defaultRoute=None)
    h7 = topo.addHost('h7', cls=Host, ip='10.0.0.7', defaultRoute=None)
    h8 = topo.addHost('h8', cls=Host, ip='10.0.0.8', defaultRoute=None)
    h9 = topo.addHost('h9', cls=Host, ip='10.0.0.9', defaultRoute=None)
    h10 = topo.addHost('h10', cls=Host, ip='10.0.0.10', defaultRoute=None)
    h11 = topo.addHost('h11', cls=Host, ip='10.0.0.11', defaultRoute=None)
    h12 = topo.addHost('h12', cls=Host, ip='10.0.0.12', defaultRoute=None)
    h13 = topo.addHost('h13', cls=Host, ip='10.0.0.13', defaultRoute=None)
    h14 = topo.addHost('h14', cls=Host, ip='10.0.0.14', defaultRoute=None)
    h15 = topo.addHost('h15', cls=Host, ip='10.0.0.15', defaultRoute=None)
    h16 = topo.addHost('h16', cls=Host, ip='10.0.0.16', defaultRoute=None)
    h17 = topo.addHost('h17', cls=Host, ip='10.0.0.17', defaultRoute=None)
    h18 = topo.addHost('h18', cls=Host, ip='10.0.0.18', defaultRoute=None)

    info('*** Adding links\n')
    topo.addLink(h1, s8, 1, 1, cls=TCLink, bw=1)
    topo.addLink(s8, s7, 2, 2, cls=TCLink, bw=1)
    topo.addLink(s7, s5, 3, 3, cls=TCLink, bw=1)
    topo.addLink(s7, s6, 4, 4, cls=TCLink, bw=1)
    topo.addLink(h2, s10, 5, 5, cls=TCLink, bw=1)
    topo.addLink(s10, s9, 6, 6, cls=TCLink, bw=1)
    topo.addLink(s9, s5, 7, 7, cls=TCLink, bw=1)
    topo.addLink(s9, s6, 8, 8, cls=TCLink, bw=1)
    topo.addLink(s5, s1, 9, 9, cls=TCLink, bw=1)
    topo.addLink(s6, s2, 10, 10, cls=TCLink, bw=1)
    topo.addLink(h3, s14, 11, 11, cls=TCLink, bw=1)
    topo.addLink(s14, s13, 12, 12, cls=TCLink, bw=1)
    topo.addLink(s13, s11, 13, 13, cls=TCLink, bw=1)
    topo.addLink(s13, s12, 14, 14, cls=TCLink, bw=1)
    topo.addLink(h4, s16, 15, 15, cls=TCLink, bw=1)
    topo.addLink(s16, s15, 16, 16, cls=TCLink, bw=1)
    topo.addLink(s15, s11, 17, 17, cls=TCLink, bw=1)
    topo.addLink(s15, s12, 18, 18, cls=TCLink, bw=1)
    topo.addLink(s11, s2, 19, 19, cls=TCLink, bw=1)
    topo.addLink(s12, s3, 20, 20, cls=TCLink, bw=1)
    topo.addLink(h5, s20, 21, 21, cls=TCLink, bw=1)
    topo.addLink(s20, s19, 22, 22, cls=TCLink, bw=1)
    topo.addLink(s19, s17, 23, 23, cls=TCLink, bw=1)
    topo.addLink(s19, s18, 24, 24, cls=TCLink, bw=1)
    topo.addLink(h6, s22, 25, 25, cls=TCLink, bw=1)
    topo.addLink(s22, s21, 26, 26, cls=TCLink, bw=1)
    topo.addLink(s21, s17, 27, 27, cls=TCLink, bw=1)
    topo.addLink(s21, s18, 28, 28, cls=TCLink, bw=1)
    topo.addLink(s17, s3, 29, 29, cls=TCLink, bw=1)
    topo.addLink(s18, s4, 30, 30, cls=TCLink, bw=1)
    topo.addLink(h7, s30, 31, 31, cls=TCLink, bw=1)
    topo.addLink(s30, s29, 32, 32, cls=TCLink, bw=1)
    topo.addLink(s29, s27, 33, 33, cls=TCLink, bw=1)
    topo.addLink(s29, s28, 34, 34, cls=TCLink, bw=1)
    topo.addLink(h8, s32, 35, 35, cls=TCLink, bw=1)
    topo.addLink(s32, s31, 36, 36, cls=TCLink, bw=1)
    topo.addLink(s31, s27, 37, 37, cls=TCLink, bw=1)
    topo.addLink(s31, s28, 38, 38, cls=TCLink, bw=1)
    topo.addLink(s27, s23, 39, 39, cls=TCLink, bw=1)
    topo.addLink(s28, s24, 40, 40, cls=TCLink, bw=1)
    topo.addLink(h9, s36, 41, 41, cls=TCLink, bw=1)
    topo.addLink(s36, s35, 42, 42, cls=TCLink, bw=1)
    topo.addLink(s35, s33, 43, 43, cls=TCLink, bw=1)
    topo.addLink(s35, s34, 44, 44, cls=TCLink, bw=1)
    topo.addLink(h10, s38, 45, 45, cls=TCLink, bw=1)
    topo.addLink(s38, s37, 46, 46, cls=TCLink, bw=1)
    topo.addLink(s37, s33, 47, 47, cls=TCLink, bw=1)
    topo.addLink(s37, s34, 48, 48, cls=TCLink, bw=1)
    topo.addLink(s33, s24, 49, 49, cls=TCLink, bw=1)
    topo.addLink(s34, s25, 50, 50, cls=TCLink, bw=1)
    topo.addLink(h11, s42, 51, 51, cls=TCLink, bw=1)
    topo.addLink(s42, s41, 52, 52, cls=TCLink, bw=1)
    topo.addLink(s41, s39, 53, 53, cls=TCLink, bw=1)
    topo.addLink(s41, s40, 54, 54, cls=TCLink, bw=1)
    topo.addLink(h12, s44, 55, 55, cls=TCLink, bw=1)
    topo.addLink(s44, s43, 56, 56, cls=TCLink, bw=1)
    topo.addLink(s43, s39, 57, 57, cls=TCLink, bw=1)
    topo.addLink(s43, s40, 58, 58, cls=TCLink, bw=1)
    topo.addLink(s39, s25, 59, 59, cls=TCLink, bw=1)
    topo.addLink(s40, s26, 60, 60, cls=TCLink, bw=1)
    topo.addLink(s1, s23, 61, 61, cls=TCLink, bw=1)
    topo.addLink(s2, s24, 62, 62, cls=TCLink, bw=1)
    topo.addLink(s3, s25, 63, 63, cls=TCLink, bw=1)
    topo.addLink(s4, s26, 64, 64, cls=TCLink, bw=1)
    topo.addLink(h13, s52, 65, 65, cls=TCLink, bw=1)
    topo.addLink(s52, s51, 66, 66, cls=TCLink, bw=1)
    topo.addLink(s51, s49, 67, 67, cls=TCLink, bw=1)
    topo.addLink(s51, s50, 68, 68, cls=TCLink, bw=1)
    topo.addLink(h14, s54, 69, 69, cls=TCLink, bw=1)
    topo.addLink(s54, s53, 70, 70, cls=TCLink, bw=1)
    topo.addLink(s53, s49, 71, 71, cls=TCLink, bw=1)
    topo.addLink(s53, s50, 72, 72, cls=TCLink, bw=1)
    topo.addLink(s49, s45, 73, 73, cls=TCLink, bw=1)
    topo.addLink(s50, s46, 74, 74, cls=TCLink, bw=1)
    topo.addLink(h15, s58, 75, 75, cls=TCLink, bw=1)
    topo.addLink(s58, s57, 76, 76, cls=TCLink, bw=1)
    topo.addLink(s57, s55, 77, 77, cls=TCLink, bw=1)
    topo.addLink(s57, s56, 78, 78, cls=TCLink, bw=1)
    topo.addLink(h16, s60, 79, 79, cls=TCLink, bw=1)
    topo.addLink(s60, s59, 80, 80, cls=TCLink, bw=1)
    topo.addLink(s59, s55, 81, 81, cls=TCLink, bw=1)
    topo.addLink(s59, s56, 82, 82, cls=TCLink, bw=1)
    topo.addLink(s55, s46, 83, 83, cls=TCLink, bw=1)
    topo.addLink(s56, s47, 84, 84, cls=TCLink, bw=1)
    topo.addLink(h17, s64, 85, 85, cls=TCLink, bw=1)
    topo.addLink(s64, s63, 86, 86, cls=TCLink, bw=1)
    topo.addLink(s63, s61, 87, 87, cls=TCLink, bw=1)
    topo.addLink(s63, s62, 88, 88, cls=TCLink, bw=1)
    topo.addLink(h18, s66, 89, 89, cls=TCLink, bw=1)
    topo.addLink(s66, s65, 90, 90, cls=TCLink, bw=1)
    topo.addLink(s65, s61, 91, 91, cls=TCLink, bw=1)
    topo.addLink(s65, s62, 92, 92, cls=TCLink, bw=1)
    topo.addLink(s61, s47, 93, 93, cls=TCLink, bw=1)
    topo.addLink(s62, s48, 94, 94, cls=TCLink, bw=1)
    topo.addLink(s23, s45, 95, 95, cls=TCLink, bw=1)
    topo.addLink(s24, s46, 96, 96, cls=TCLink, bw=1)
    topo.addLink(s25, s47, 97, 97, cls=TCLink, bw=1)
    topo.addLink(s26, s48, 98, 98, cls=TCLink, bw=1)


class MyTopo(Topo):
    def __init__(self):
        Topo.__init__(self)
        _init(self)


def myNetwork(standalone = False):
    net = Mininet(
        topo=None,
        build=False,
        ipBase="10.0.0.0/8"
    )

    info('*** Adding controller\n')
    c0=net.addController(
        name='c0',
        controller=RemoteController,
        ip='127.0.0.1',
        protocol='tcp',
        port=6633
    )

    _init(net)

    info('*** Starting network\n')
    net.build()

    info('*** Starting controllers\n')
    for controller in net.controllers:
        controller.start()

    info('*** Starting switches\n')
    net.get('s1').start([c0])
    net.get('s2').start([c0])
    net.get('s3').start([c0])
    net.get('s4').start([c0])
    net.get('s5').start([c0])
    net.get('s6').start([c0])
    net.get('s7').start([c0])
    net.get('s8').start([c0])
    net.get('s9').start([c0])
    net.get('s10').start([c0])
    net.get('s11').start([c0])
    net.get('s12').start([c0])
    net.get('s13').start([c0])
    net.get('s14').start([c0])
    net.get('s15').start([c0])
    net.get('s16').start([c0])
    net.get('s17').start([c0])
    net.get('s18').start([c0])
    net.get('s19').start([c0])
    net.get('s20').start([c0])
    net.get('s21').start([c0])
    net.get('s22').start([c0])
    net.get('s23').start([c0])
    net.get('s24').start([c0])
    net.get('s25').start([c0])
    net.get('s26').start([c0])
    net.get('s27').start([c0])
    net.get('s28').start([c0])
    net.get('s29').start([c0])
    net.get('s30').start([c0])
    net.get('s31').start([c0])
    net.get('s32').start([c0])
    net.get('s33').start([c0])
    net.get('s34').start([c0])
    net.get('s35').start([c0])
    net.get('s36').start([c0])
    net.get('s37').start([c0])
    net.get('s38').start([c0])
    net.get('s39').start([c0])
    net.get('s40').start([c0])
    net.get('s41').start([c0])
    net.get('s42').start([c0])
    net.get('s43').start([c0])
    net.get('s44').start([c0])
    net.get('s45').start([c0])
    net.get('s46').start([c0])
    net.get('s47').start([c0])
    net.get('s48').start([c0])
    net.get('s49').start([c0])
    net.get('s50').start([c0])
    net.get('s51').start([c0])
    net.get('s52').start([c0])
    net.get('s53').start([c0])
    net.get('s54').start([c0])
    net.get('s55').start([c0])
    net.get('s56').start([c0])
    net.get('s57').start([c0])
    net.get('s58').start([c0])
    net.get('s59').start([c0])
    net.get('s60').start([c0])
    net.get('s61').start([c0])
    net.get('s62').start([c0])
    net.get('s63').start([c0])
    net.get('s64').start([c0])
    net.get('s65').start([c0])
    net.get('s66').start([c0])

    if standalone:
        info('*** Post configure switches and hosts\n')
        CLI(net)
        net.stop()

    return net


topos = {'mytopo': MyTopo}


if __name__ == "__main__":
    setLogLevel("info")
    myNetwork(True)
